{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Description\n",
    "This notebook conducts an experiment based on the targeted harmful object removal experiment from the paper (Section 4.5, B). The goal of the experiment is to check whether Influence Functions for GBDT provides a reliable way of \"targeting\" a particular difficult test object $\\mathbf{x_{test}}$ and identifying training objects $\\mathbf{x_{train}}$ \"harmul\" specifically for the test object at hand.\n",
    "\n",
    "The plan of the experiment is as follows:\n",
    "- Read train/test data, introduce noise into the train set\n",
    "- Calculate two \"scores\" prioritizing points to remove:\n",
    "    - **LeafInfluence**: Derivative of the Logloss on $\\mathbf{x_{test}}$ w.r.t. the weight of $\\mathbf{x_{train}}$: $\\frac{\\partial L(y_{test}, F(x_{test}, \\mathbf{w})}{\\partial w_{\\mathbf{x_{train}}}}$\n",
    "    - **Detector**: Prediction of the model (trained on noisy data) w.r.t. to the opposite class. This is a noise detection method that is unable to target specific test points.\n",
    "- Iteratively remove training points from the train set and measure how the Logloss changes on $\\mathbf{x_{test}}$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.path.insert(0, '../')\n",
    "sys.path.insert(0, '../influence_boosting')\n",
    "\n",
    "import os\n",
    "import pickle\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "from sklearn.metrics import log_loss\n",
    "from tqdm import tqdm, tqdm_notebook\n",
    "from copy import deepcopy\n",
    "from catboost import CatBoostClassifier\n",
    "from ipywidgets import IntProgress\n",
    "\n",
    "from data.adult import read_train_documents_and_one_hot_targets\n",
    "from util import read_json_params, export_catboost_to_json\n",
    "from influence_boosting.influence.leaf_influence import CBLeafInfluenceEnsemble"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Reading and preparing data\n",
    "First, we read our train and test datasets:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_data, train_targets = read_train_documents_and_one_hot_targets('../data/adult/train_data_catboost_format.tsv')\n",
    "train_targets = np.argmax(train_targets, axis=1)\n",
    "test_data, test_targets = read_train_documents_and_one_hot_targets('../data/adult/test_data_catboost_format.tsv')\n",
    "test_targets = np.argmax(test_targets, axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then inject random noise into training labels:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def make_nonuniform_noisy_sample(targets, flip_frac, p=None, seed=10):\n",
    "    \"\"\"\n",
    "    Choose int(len(targets) * flip_frac) points for flipping. Probability of flipping is proportional to p.\n",
    "    \"\"\"\n",
    "    if seed is not None:\n",
    "        np.random.seed(seed)\n",
    "    if p is None:\n",
    "        p = np.ones(len(targets))\n",
    "    p /= np.sum(p)\n",
    "    perturbed_idxs = np.random.choice(len(targets), size=int(len(targets) * flip_frac), replace=False, p=p)\n",
    "    result = deepcopy(targets)\n",
    "    perturbed_idxs_mask = np.zeros_like(targets)\n",
    "    for perturbed_i in perturbed_idxs:\n",
    "        result[perturbed_i] = 1 - result[perturbed_i]\n",
    "        perturbed_idxs_mask[perturbed_i] = 1\n",
    "    return result, perturbed_idxs_mask\n",
    "\n",
    "np.random.seed(20)\n",
    "frac = 4000 / float(len(train_targets))\n",
    "train_targets_polluted, polluted_gt = make_nonuniform_noisy_sample(train_targets, frac, seed=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Obtain scores\n",
    "We now fix a particular test index that we would like to target and calculate the \"scores\" of the train points w.r.t. this test point."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "test_idx = 899"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Temporary training directory:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_dir = '../data/adult/catboost_tmp_dir'\n",
    "if not os.path.exists(train_dir):\n",
    "    os.mkdir(train_dir)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Read CatBoost parameters and train the model on the noisy data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<catboost.core._CatBoostBase at 0x7ff06cc591d0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "catboost_params = read_json_params('../data/adult/catboost_params.json')\n",
    "catboost_params['train_dir'] = train_dir\n",
    "catboost_params['random_seed'] = 10\n",
    "cbc = CatBoostClassifier(**catboost_params)\n",
    "cbc.fit(train_data, train_targets_polluted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Save the model, export it to JSON and create a ``CBLeafInfluenceEnsemble`` using this JSON. We will use the smallest Update Set (see Section 3.1.2 of the paper) to save time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "cbc.save_model(train_dir + '/model.bin')\n",
    "export_catboost_to_json(train_dir + '/model.bin', train_dir + '/model.json')\n",
    "leafinfluence = CBLeafInfluenceEnsemble(train_dir + '/model.json', train_data, train_targets_polluted,\n",
    "                                        leaf_method=catboost_params['leaf_estimation_method'],\n",
    "                                        learning_rate=catboost_params['learning_rate'],\n",
    "                                        update_set='SinglePoint')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Calculate loss derivatives (**LeafInfluence**):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "influence_scores = []\n",
    "buf = deepcopy(leafinfluence)\n",
    "for i in tqdm_notebook(xrange(len(train_data))):\n",
    "    leafinfluence.fit(removed_point_idx=i, destination_model=buf)\n",
    "    influence_scores.append(buf.loss_derivative(test_data[[test_idx]], test_targets[[test_idx]])[0])\n",
    "influence_scores = np.array(influence_scores)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Calculate **Detector** scores:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "detector_scores = cbc.predict_proba(train_data)[xrange(len(train_data)), 1 - train_targets_polluted]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Measure loss reductions\n",
    "We proceed to iteratively remove train points according to the obtained scores and measure how this affects the losses on ``test_idx``.\n",
    "\n",
    "Utility functions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def catboost_fit_predict(train_documents, train_targets, test_documents, prediction_type='RawFormulaVal',\n",
    "                         **catboost_params):\n",
    "    if 'gpu_ram_part' in catboost_params:\n",
    "        gpu_ram_part = catboost_params.pop('gpu_ram_part')\n",
    "    else:\n",
    "        gpu_ram_part = None\n",
    "    cbc = CatBoostClassifier(**catboost_params)\n",
    "    if gpu_ram_part is not None:\n",
    "        cbc.set_params(gpu_ram_part=gpu_ram_part)\n",
    "    cbc.fit(train_documents, train_targets)\n",
    "    return cbc.predict(test_documents, prediction_type)\n",
    "\n",
    "def prediction_fidelity_after_iterative_fixing(train_documents, train_targets, test_documents, test_targets, test_idx,\n",
    "                                               scores, batch_size, max_steps, **catboost_params):\n",
    "    prediction_original = catboost_fit_predict(train_documents, train_targets, test_documents,\n",
    "                                               'Probability', **catboost_params)\n",
    "    loss_on_test_idx_original = log_loss(y_true=test_targets[[test_idx]], y_pred=prediction_original[[test_idx]],\n",
    "                                        labels=[0, 1])\n",
    "    \n",
    "    losses_on_test_idx = []\n",
    "    batch_num = 0\n",
    "    harmful_idxs_queue = np.argsort(-scores)\n",
    "    idxs_to_remove = []\n",
    "    pbar = tqdm_notebook(total=max_steps + 1)\n",
    "    while len(train_documents) - len(idxs_to_remove) > batch_size and batch_num < max_steps + 1:\n",
    "        first_new_removed_idx = (batch_num - 1) * batch_size\n",
    "        idxs_to_remove_batch = harmful_idxs_queue[first_new_removed_idx:first_new_removed_idx + batch_size]\n",
    "        idxs_to_remove += list(idxs_to_remove_batch)\n",
    "        train_documents_reduced = np.delete(train_documents, idxs_to_remove, axis=0)\n",
    "        train_targets_reduced = np.delete(train_targets, idxs_to_remove, axis=0)\n",
    "        prediction = catboost_fit_predict(train_documents_reduced, train_targets_reduced, test_documents,\n",
    "                                          'Probability', **catboost_params)\n",
    "        loss_on_test_idx = log_loss(y_true=test_targets[[test_idx]], y_pred=prediction[[test_idx]], labels=[0, 1])\n",
    "        losses_on_test_idx.append((loss_on_test_idx - loss_on_test_idx_original) / loss_on_test_idx_original)\n",
    "        batch_num += 1\n",
    "        pbar.update(1)\n",
    "    pbar.close()\n",
    "    return losses_on_test_idx"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run calculations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "losses_on_test_idx_for_scores = {}\n",
    "losses_on_test_idx_for_scores['LeafInfluence'] = prediction_fidelity_after_iterative_fixing(\n",
    "    train_data, train_targets_polluted, test_data, test_targets, test_idx, influence_scores, 50, 80, **catboost_params\n",
    ")\n",
    "losses_on_test_idx_for_scores['Detector'] = prediction_fidelity_after_iterative_fixing(\n",
    "    train_data, train_targets_polluted, test_data, test_targets, test_idx, detector_scores, 50, 80, **catboost_params\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Plot the results:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZQAAAEKCAYAAAA1qaOTAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXeYXFXd+D/fme01W9LIpickEBIS2ICCQESaAoIFFRtBfREV62sBfRWsLyov/KxIRAUUBUERRBHpIDUJPY30ZDdlk+xme5ud8/vj3LNzd3bKnZ26u+fzPPPcuW3umXa/59tFKYXFYrFYLMniy/YALBaLxTI2sALFYrFYLCnBChSLxWKxpAQrUCwWi8WSEqxAsVgsFktKsALFYrFYLCnBChSLxWKxpISsChQROUdENonIFhG5MsL+G0TkZefxhogcdu0bcO27L7Mjt1gsFks4kq3ERhHxA28AZwINwGrgYqXU+ijHfxZYppT6mLPeoZQqy9R4LRaLxRKbvCxe+wRgi1JqG4CI3AFcAEQUKMDFwNXJXLC2tlbNmjUrmZewWCyWccfatWsPKqUmxjsumwJlGrDbtd4AnBjpQBGZCcwGHnVtLhKRNUAAuFYp9bd4F5w1axZr1qwZ+YgtFotlHCIiO70cl02BkggfAO5WSg24ts1USjWKyBzgURF5TSm1NfxEEbkMuAxgxowZmRmtxWKxjEOy6ZRvBKa71uucbZH4APAn9walVKOz3AY8DiyLdKJSapVSql4pVT9xYlyNzWKxWCwjJJsCZTUwX0Rmi0gBWmgMi9YSkYVAFfCsa1uViBQ6z2uBk4nue7FYLBZLBsiayUspFRCRK4AHAT/wW6XUOhH5DrBGKWWEyweAO9TQcLSjgJtEJIgWitdGiw6zWCy5RX9/Pw0NDfT09GR7KJYwioqKqKurIz8/f0TnZy1sOBvU19cr65S3WLLL9u3bKS8vp6amBhHJ9nAsDkopDh06RHt7O7Nnzx6yT0TWKqXq472GzZS3WCwZpaenxwqTHEREqKmpSUpztALFYrFkHCtMcpNkvxcrUCyWbNPaAJv+le1RWCxJYwWKxZJtVv8G7vwwjCN/ZrYpK0tN1aaLL76YJUuWcMMNN7By5UruvvvumMf39vZyxhlnsHTpUu68805WrFgxppKtR0tio8UydunrhGC/Xhba8nSjhX379rF69Wq2bNkCwMqVK+Oe89JLLwHw8ssvA3DjjTembXzZwGooFku2CThO0N727I5jnHPgwAHe8573sHz5cpYvX87TTz8NwAsvvMCb3/xmli1bxkknncSmTZsAOOuss2hsbGTp0qU89dRTQ15r1qxZXH311Rx33HEsXryYjRs30tTUxIc//GFWr17N0qVL2bp1aGEPt9Z09913DwqoaOO65ppr+NjHPsaKFSuYM2cOP/3pTwfPv+2221iyZAnHHnssH/nIR2K+TiqxGorFkm0GBUobMDWrQ8k03/77OtbvaUvpax59RAVXn78o4fM+//nP88UvfpG3vOUt7Nq1i7PPPpsNGzawcOFCnnrqKfLy8nj44Yf5+te/zl/+8hfuu+8+zjvvvEFt4ze/+c2Q16utreXFF1/kl7/8Jddddx0333wzN998M9dddx33339/0uMC2LhxI4899hjt7e0sWLCAT33qU7zxxht873vf45lnnqG2tpbm5ua4r5MqrECxWLKN1VBygocffpj160P50W1tbXR0dNDa2soll1zC5s2bERH6+/s9vd673/1uAI4//nj++te/pnxcAOeeey6FhYUUFhYyadIk9u/fz6OPPspFF11EbW0tANXV1TFfJ1X+JLACxWLJPv2OQOlpze44ssBINIl0EQwGee655ygqKhqy/YorruCtb30r99xzDzt27GDFihWeXq+wsBAAv99PIBCIe7w7ZNedCxJtXO5reLlOrNdJFdaHYrFkm0C3XloNJaucddZZ/OxnPxtcN6as1tZWpk2bBsAtt9yStutPnjyZDRs2EAwGueeee+KOKxqnn346d911F4cOHQIYNHkl+jojwQoUiyXbBHr1sje1vgRLdLq6uqirqxt8XH/99fz0pz9lzZo1LFmyhKOPPppf/epXAHz1q1/lqquuYtmyZZ40jZFy7bXXct5553HSSScxdWrIlxZtXNFYtGgR3/jGNzjttNM49thj+dKXvjSi1xkJtpaXxZJtfnUK7HsVzvo+nHRFtkeTdjZs2MBRRx2V7WFYohDp+7G1vCyW0cKghmJNXpbRjRUoFku2GfShWJOXZXRjBYrFkm2sD8UyRrACxWLJNoNhw1agWEY3VqBYLNnGhg1bxghWoFgs2SQYhIE+/dyavCyjHCtQLJZsEnB1x7MaSsbw+/0sXbqURYsWceyxx/J///d/BIPBmOfs2LGDP/7xjyO+5i233MKePXtGfP5owAoUiyWbuAWK9aFkjOLiYl5++WXWrVvHQw89xAMP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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7ff038d7cf50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for name in losses_on_test_idx_for_scores:\n",
    "    plt.plot(losses_on_test_idx_for_scores[name], label=name)\n",
    "plt.xlabel('Num batches')\n",
    "plt.ylabel('Relative logloss change')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although, as demonstrated in Section 4.5, A, **Detector** is a slightly stronger noise detector \"on average\", this plot demonstrates that **LeafInfluence** greatly outperforms it in targeting training objects harmful for the specific $\\mathbf{x_{test}}$."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "influence_boosting",
   "language": "python",
   "name": "influence_boosting"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
